/*
 * Enlace.h
 *
 *	Biblioteca responsavel por listar as funções requeridas na camada de enlace
 *	segundo o protocolo 802.5(Token Ring)
 *
 *  Created on: 09/06/2011
 *      Authors: Erick e Glauco
 */

#ifndef ENLACE_H_
#define ENLACE_H_

/*
 * Formatação do Quadro no TOKEN RING (original)
 *
 * Formato do Quadro: SD|AC|FC|DA|SA|DADOS|FCS|ED|FS
 *
 * SD: delimitador do quadro JK0JKOOO  - não será utilizado pois o quadro tem tamanho FIXO
 * AC:octeto (Prioridade(2)-Tipo(1)-Monitor(1)-Reserva(2))
 *
 * Prioridade (2 bits)
 * 00 - 01 - 10 - 11
 *
 * Tipo (1 bit)
 * 	- 0: Permissão
 *  - 1: Dados
 *
 * Monitor (1 bit)
 *  - 0: não passou pelo monitor
 *  - 1: passou pelo monitor
 *
 * Reserva: (2 bits) : reserva para requerir a próxima permissão - não será utilizado
 *
 * Broadcast (1 bit)
 *  - 0: apenas o destino lê a mensagem
 *  - 1: todos leem a mensagem
 *
 *
 * DA: Endereço do Destino (4 bits)
 *
 * SA: Endereço da Origem (4 bits)
 *
 * Quadro Intermediário (1 bit)
 *  - 0: quadro final
 *  - 1: quadro intermediário
 *
 * Dados: (0 ou Mais bits)
 *
 * FCS: Detecção de Erros (CRC-8) (8 bits)
 *
 *
 * ED: delimitador de fim de quadro - nao sera utilizado pois o quadro tem tamanho fixo
 *
 * FS: octeto com o padrão: ACrrACrr - nao sera utilizado
 * - A é colocado em 1 quando a estação reconhece ser o destino
 * - C é colcado em 1 se a estação de destino copiou o quadro transmitido
 */

/*********** Definiçao dos TAMANHOS DOS CAMPOS no quadros *****************/

/*********** TAMANHO DO QUADRO FINAL = 64 bits ****************************/

// o quadro sem dados tem tamanho 22
#define TAMANHO_QUADRO 22
// o campo de dados consite em 42 bits
#define TAMANHO_DADOS 48
// o campo de token precisa de 4 bits
#define TAMANHO_TOKEN 4
// o campo de prioridade precisa de 2 bits
#define TAMANHO_PRIORIDADE 2
// o campo de MAC precisa de 4bits
#define TAMANHO_MAC 4
// o campo de CRC precisa de 8 bits
#define TAMANHO_CRC 8

/******************* FIM da definição *************************************/


/*********** Definicao das LOCALIZACOES DOS BITS no quadro final *********/

// FORMATAÇÃO:
/* PRIORIDADE|TIPO|MONITOR|BROADCAST|DESTINO|ORIGEM|INTERMEDIARIO|DADOS */

#define LOCALIZACAO_PRIORIDADE 0
#define LOCALIZACAO_TIPO 2
#define LOCALIZACAO_MONITOR 3
#define LOCALIZACAO_BROADCAST 4
#define LOCALIZACAO_DESTINO 5
#define LOCALIZACAO_ORIGEM 9
#define LOCALIZACAO_INTERMEDIARIO 13
#define LOCALIZACAO_DADOS 14

/******************* FIM da definição *************************************/

#include <list>
#include <vector>
#include <iterator>
#include <map>
#include "Bits.h"
#include "Layer.hpp"
#include <boost/thread.hpp>


using namespace std;
using namespace ufpb::project::network;

class Enlace : public Layer {
public:
    // meu endereco MAC
    int mac;
    // numero do monitor
    int monitor;
    // minha prioridade
    int prioridade;
    // armazenará as mensagens recebidas
    Bits** mensagensRecebidas;
    // armazenara se a mensagem sera descartada
    bool* mensagensDescartadas;


    //lock para sincronizar o envio dos quadros
    boost::condition_variable condEnvia;
    boost::mutex envia;
    //lock para sincronizar o recebimento dos quadros
    boost::condition_variable condRecebe;
    boost::mutex recebe;

    //mutex que gerencia quem quer mandar
    boost::mutex *querLock;
    //mutex que gerencia quem pode mandar
    boost::mutex *naoEnviaLock;

    //variavel que seta se existe alguem que quer enviar dados
    bool querEnviar;

    //varial que seta se alguem pode enviar dados
    bool PodeEnviar;


    // Construtor
    Enlace(int mac);

    //Enlace(map<string,string> conf);

    // ~Destrutor
    ~Enlace();

    //função que seta se a thread quer enviar ou nao
    void setQuerEnviar(bool querEnviar);

    //função que seta se a thread pode enivar ou nao
    void setPodeEnviar(bool podeEnviar);

    //função que retorna se a thread quer enviar
    bool getQuerEnviar();

    //funçao que retorna se a thread pode enviar
    bool getPodeEnviar();


    // Função que cria os Quadros
    vector<Bits*> EnquadraBits(Bits* dados);

    // desenquadra os quadros tornando separado o token dos dados
    Bits* Desenquadra(Bits* quadro);

    //Funcao que remove o quadro do anel
    void RemoveQuadro(Bits* quadro);

    // Funcao que monitora os quadros
    void MonitoraQuadros(Bits *quadro);

    /* Funcao: CriaToken()
     * Funcao que cria um novo token com a prioridade passada como parametro
     * @param: prioridade
     * @return: array de Bits
     * */
    Bits* CriaToken(int prioridade);

    // funcao que checa se a prioridade do token é maior que a minha
    bool ChecaPrioridade(Bits* quadro);

    // reserva o Token para minha transmissão
    bool ReservaToken(Bits* quadro);

    // verifica se o quadro possui erros
    bool ChecaErros(Bits* quadro);

    // calcula o valor do crc8
    int CheckCrc8(Bits* bits);

    //metodos da classe Layer
    void newMessageToSend(Bits* m);
    void newReceivedMessage(Bits* m);
    void init();
    //Layer* getDownLayer();
};




#endif /* ENLACE_H_ */
